当前位置:  开发笔记 > 后端 > 正文

为什么`-1*x`比`-x`快?为什么?

如何解决《为什么`-1*x`比`-x`快?为什么?》经验,为你挑选了1个好方法。

使用此代码:

include Benchmark
n = 10**8
r = []
Benchmark.benchmark(" "*7 + CAPTION, 7, FORMAT, ">avg:", ">total:") do |b|
  a = 1

  r << b.report("Benchmark -1:")   { (n).times do
    -1 * a
  end }

  r << b.report("Benchmark - :")   { (n).times do
    -a
  end }

  [(r.sum{|e| e }) / 2, r.sum{|e| e }]
end

我得到了这个结果ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]:

                     user     system      total        real
Benchmark -1:  4.930000   0.000000   4.930000 (  4.938359)
Benchmark - :  5.650000   0.000000   5.650000 (  5.667566)
>avg:     5.290000   0.000000   5.290000 (  5.302962)
>total:  10.580000   0.000000  10.580000 ( 10.605924)

这看起来很反直,因为如果我猜我会打赌"-x"而不是"-1*x"更快.

为什么不同?或者我的测量中存在一些重大缺陷?



1> eugen..:

如果查看生成的字节码,它可能会有所帮助.如果你把它简化为简单的东西

puts RubyVM::InstructionSequence.compile(<<-CODE
a = 1
-1 * a
CODE
).to_a.join("\n")


puts RubyVM::InstructionSequence.compile(<<-CODE
a = 1
-a
CODE
).to_a.join("\n")

您还可以使用#~$ ruby --dump insns -e 'code'打印指令序列(如@Stefan所述),它将实际输出更清晰的输出.

#~$ ruby --dump insns -e 'a = 1; -a'
== disasm: @-e>======================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] a          
0000 trace            1                                               (   1)
0002 putobject        1
0004 setdynamic       a, 0
0007 trace            1
0009 getdynamic       a, 0
0012 send             :-@, 0, nil, 0, 
0018 leave            
#~$ ruby --dump insns -e 'a = 1; -1 * a'
== disasm: @-e>======================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] a          
0000 trace            1                                               (   1)
0002 putobject        1
0004 setdynamic       a, 0
0007 trace            1
0009 putobject        -1
0011 getdynamic       a, 0
0014 opt_mult         
0016 leave

你会注意到在字节码列表中,在-1 * aRuby中opt_mult它实际上只是一个算术运算,并在内部进行了优化.另一方面,该-a位是opt_send_without_block实际的方法调用.我的猜测是这就是为什么第二个版本(有点)慢了.


注意你也可以执行`ruby --dump insns -e'a = 1; -a'`打印指令序列.
推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有